package singleThreaded;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;

import net.htmlparser.jericho.Element;
import net.htmlparser.jericho.HTMLElementName;
import net.htmlparser.jericho.Source;

/**
 * Page parser class. This will parse the source into links and text.
 * @author Son Pham
 * @version 1.0
 */
public class PageParser
{
  /**
   * A queue of extracted links from this web page.
   */
  private Queue<String> my_links;
  
  /**
   * The raw source of a web page.
   */
  private final Source my_source;
 
  /**
   * The protocol of this web page.
   */
  private final String my_protocol;
  
  /**
   * The host of this web page.
   */
  private final String my_host;
  
  /**
   * All text from this web page.
   */
  private String my_text;
  
  /**
   * Construct a PageParser object with the input source.
   * @param the_source The source.
   */
  public PageParser(final Source the_source, final String the_protocol, final String the_host)
  {
    my_source = the_source;
    my_links = new PriorityQueue<String>();
    my_protocol = the_protocol;
    my_host = the_host;
    my_text = "";
  }
  
  /**
   *
   * @return The source of this parser.
   */
  public Source getSource()
  {
    return my_source;
  }
  
  /**
   * 
   * @param the_link The link (could be relative).
   * @param the_protocol The protocol.
   * @param the_host The host.
   * @return The full and "clean" URL.
   * @throws MalformedURLException Malformed URL Exception.
   */
  /*
  private static URL tidyLink(final String the_link, 
                              final String the_protocol, 
                              final String the_host) throws MalformedURLException
  {
    final URL full_url;
    String temp_link = the_link;
    
    // Remove bookmarks
    final int pos = temp_link.indexOf('#');
    if (pos != -1)
    {
      temp_link = temp_link.substring(0, pos);
    }
    
    // Remove trailing "/"
    if (temp_link.length() > 0 && temp_link.endsWith("/"))
    {
      temp_link = temp_link.substring(0, temp_link.length() - 1);
    }
    
    // check to see whether it ends with .htm, .html, .txt or a relative link

    if (temp_link.contains("."))
    {
      // Only accept the links ending with .htm, .html or .txt
      if (temp_link.endsWith(".htm") || temp_link.endsWith(".html") ||
          temp_link.endsWith(".txt"))
      {
        // Check if's it's a relative url.
        if (temp_link.indexOf("/") == 0)
        {
          full_url = new URL(the_protocol, the_host, temp_link);
        }
        else
        {
          full_url = new URL(temp_link);
        }
      }
      else
      {
        full_url = new URL("");
      }
    }
    else
    {
      // Check if it's a relative url.
      if (temp_link.indexOf("/") == 0 || temp_link.length() == 0)
      {
        full_url = new URL(the_protocol, the_host, temp_link);
      }
      else
      {
        full_url = new URL(temp_link);
      }
    }
    
    /*
    if (!temp_link.endsWith(".gz") && 
        !temp_link.endsWith(".rar") && 
        !temp_link.endsWith(".zip") &&
        !temp_link.endsWith(".mp3") &&
        !temp_link.endsWith(".flv") &&
        !temp_link.startsWith("mailto"))
    {
    
      // Retrieve full URL
      if (temp_link.indexOf("/") == 0 || temp_link.length() == 0)
      {
        full_url = new URL(the_protocol, the_host, temp_link);
      }    
      else
      {
        full_url = new URL(temp_link);
      }
    }
    else
    {
      full_url = new URL("");
    }*/
    /*return full_url;
  }*/
  
  private String tidyLink(final String the_link)
  {
    String temp_link = the_link;
    String result;
    
    // Remove bookmarks
    final int pos = temp_link.indexOf('#');
    if (pos != -1)
    {
      temp_link = temp_link.substring(0, pos);
    }
    
    // Remove trailing "/"
    if (temp_link.length() > 0 && temp_link.endsWith("/"))
    {
      temp_link = temp_link.substring(0, temp_link.length() - 1);
    }
    
    result = temp_link;
    
    // check to see whether it ends with .htm, .html, or .txt
    if (temp_link.lastIndexOf('/') != -1)
    {
      temp_link = temp_link.substring(temp_link.lastIndexOf('/'), temp_link.length());
    }
    
    if (temp_link.contains("."))
    {
      // Only accept the links ending with .htm, .html or .txt
      if (!(temp_link.endsWith(".htm") || temp_link.endsWith(".html") ||
            temp_link.endsWith(".txt")))
      {
        result = "";
      }
    }
    
    final String george_blog = "questioneverything.typepad.com";
    if (result.contains(george_blog))
    {
      result = "";
    }
    
    return result;
  }
  
  private URL createURL(final String the_link, final String the_protocol, final String the_host)
      throws MalformedURLException
  {
    URL full_url;
    
    // Check if's it's a relative url.
    if (the_link.indexOf("/") == 0)
    {
      full_url = new URL(the_protocol, the_host, the_link);
    }
    else
    {
      full_url = new URL(the_link);
    }
    
    return full_url;
  }
  
  /**
   * Parse the source of the web page.
   */
  public void parse()
  {
    my_source.fullSequentialParse();
    final String empty_string = "";
    // Extract all links from the web page
    final List<Element> link_elements = my_source.getAllElements(HTMLElementName.A);
    for (Element link_element : link_elements) 
    {
      final String href = link_element.getAttributeValue("href");
      if (href == null || href.isEmpty())
      {
        continue;
      }
      try
      {
        //final URL full_url = tidyLink(href, my_protocol, my_host);
        final String the_link = tidyLink(href);
        
        if (!the_link.isEmpty())
        {
          final URL full_url = createURL(tidyLink(href), my_protocol, my_host);
          
          if (!full_url.toString().equals(empty_string))
          {
            my_links.add(full_url.toString());
          }
        }
      } 
      catch (MalformedURLException e)
      {
        // This should never happen.
      }      
    }

    my_text = my_source.getTextExtractor().setIncludeAttributes(true).toString();
  }
  
  /**
   * 
   * @return All the text of this web page.
   */
  public String getText()
  {
    return my_text;
  }
  
  /**
   * 
   * @return All extracted links from this web page.
   */
  public Queue<String> getLinks()
  {
    return my_links;
  }
}
